package dev2dev.textclient;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import dev2dev.textclient.instruct.HeartbeatProcess;

import javax.sip.SipException;
import javax.sip.message.Request;
import javax.swing.*;
import java.awt.event.*;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.*;

/***
 * 正常指令发送
 */
public class TextClient extends JFrame implements MessageProcessor {
    private SipLayer sipLayer;

    private JTextField fromAddress;
    private JLabel fromLbl;
    private JLabel receivedLbl;
    private JTextArea receivedMessages;
    private JScrollPane receivedScrollPane;
    private JButton emptyReceived;
    private JButton sendBtn;
    private JButton sendAudioPersonStartBtn;
    private JButton sendAudioStartBtn;
    private JButton sendAudioCloseBtn;
    private JLabel sendLbl;
    private JTextArea sendMessages;
    private JScrollPane sendScrollPane;
    private JTextField toAddress;
    private JLabel toLbl;
    private JTextField aisService;
    private JLabel aisServiceLbl;
    private JTextField aisMsgId;
    private JLabel aisMsgIdLbl;

    private JComboBox<String> c1 = new JComboBox<String>();//创建一个下拉列表框c1


    private List<JTextField> supplementHeadList;
    private JButton jia;
    private JButton jian;
    public int jiaNumY = 0;
    private JLabel supplementLbl;


    public static void main(String[] args) {

        try {

            /**
             * 每台：redio:都有一个 sip:709@192.168.88.241 > sip:用户电话@中继路由ip:端口
             * 启动的： 自己： from 信息**/
            Properties properties = new Properties();
            String userdir = System.getProperty("user.dir") + "/application.properties";
            try (InputStream inputStream = new FileInputStream(userdir)) {
                properties.load(inputStream);
            } catch (Exception e) {
                e.printStackTrace();
                // 处理异常
                System.out.println(" 未找到 (not found) >>> application.properties");
            }
            String username = properties.getProperty("sip.username");
            int port = Integer.parseInt(properties.getProperty("sip.port"));
            String ip = properties.getProperty("sip.ip");//该网段必须与中继器同一网端的本机IP
            SipLayer sipLayer = new SipLayer(username, ip, port);
            TextClient tc = new TextClient(sipLayer);
            sipLayer.setMessageProcessor(tc);
            //启动心跳
            HeartbeatProcess heartbeatProcess = new HeartbeatProcess(sipLayer);
            heartbeatProcess.sendHeartbeat();

            tc.show();
        } catch (Throwable e) {
            System.out.println("Problem initializing the SIP stack.");
            e.printStackTrace();
            System.exit(-1);
        }
    }

    public TextClient(SipLayer sip) {
        super();
        sipLayer = sip;
        initWindow();
        String from = "sip:" + sip.getUsername() + "@" + sip.getHost() + ":" + sip.getPort();
        this.fromAddress.setText(from);
        this.toAddress.setText("sip:711@192.168.88.241:" + sip.getPort());
    }

    private void initWindow() {
        receivedLbl = new JLabel();
        sendLbl = new JLabel();
        sendScrollPane = new JScrollPane();
        sendMessages = new JTextArea();
        receivedScrollPane = new JScrollPane();
        receivedMessages = new JTextArea();
        fromLbl = new JLabel();
        fromAddress = new JTextField();
        toLbl = new JLabel();
        toAddress = new JTextField();
        aisServiceLbl = new JLabel();
        aisService = new JTextField();
        aisMsgIdLbl = new JLabel();
        aisMsgId = new JTextField();
        supplementLbl = new JLabel();
        emptyReceived = new JButton();
        jia = new JButton();
        jian = new JButton();
        supplementHeadList = new ArrayList<>();
        sendBtn = new JButton();
        sendAudioPersonStartBtn = new JButton();
        sendAudioStartBtn = new JButton();
        sendAudioCloseBtn = new JButton();
        c1 = new JComboBox<String>();

        c1.addItem("REGISTER");  //注册
        c1.addItem("MESSAGE");   //消息 例如响铃
        c1.addItem("INVITE");       // 创建4个下拉选项
        c1.addItem("ACK");
        c1.addItem("BYE");
        c1.addItem("CANCEL");
        c1.addItem("OPTIONS");
        c1.addItem("NOTIFY");
        c1.addItem("SUBSCRIBE");
        c1.addItem("REFER");
        c1.addItem("INFO");
        c1.addItem("PRACK");
        c1.addItem("UPDATE");
        c1.addItem("PUBLISH");


        getContentPane().setLayout(null);

        setTitle("ER9000 SIP Test");
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
                System.exit(0);
            }
        });

        receivedLbl.setText("Received Messages:");
        receivedLbl.setAlignmentY(0.0F);
        receivedLbl.setPreferredSize(new java.awt.Dimension(25, 100));
        getContentPane().add(receivedLbl);
        receivedLbl.setBounds(600, 0, 136, 20);

        sendLbl.setText("Send Message:");
        getContentPane().add(sendLbl);
        sendLbl.setBounds(5, 0, 90, 20);


        sendMessages.setAlignmentX(0.0F);
        sendMessages.setLineWrap(true);
        sendMessages.setWrapStyleWord(true);
        sendScrollPane.setViewportView(sendMessages);
        sendScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        getContentPane().add(sendScrollPane);
        sendScrollPane.setBounds(5, 20, 400, 130);


        receivedMessages.setAlignmentX(0.0F);
        receivedMessages.setEditable(false);
        receivedMessages.setLineWrap(true);
        receivedMessages.setWrapStyleWord(true);
        receivedScrollPane.setViewportView(receivedMessages);
        receivedScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        getContentPane().add(receivedScrollPane);
        receivedScrollPane.setBounds(600, 20, 650, 750);

        c1.setBounds(420, 200, 140, 20);
        getContentPane().add(c1);

        fromLbl.setText("From:");
        getContentPane().add(fromLbl);
        fromLbl.setBounds(5, 200, 75, 15);

        getContentPane().add(fromAddress);
        fromAddress.setBounds(80, 200, 325, 20);
        fromAddress.setEditable(false);

        toLbl.setText("To:");
        getContentPane().add(toLbl);
        toLbl.setBounds(5, 225, 75, 15);

        getContentPane().add(toAddress);
        toAddress.setBounds(80, 225, 325, 21);


        aisServiceLbl.setText("Ais-Service:");
        getContentPane().add(aisServiceLbl);
        aisServiceLbl.setBounds(5, 255, 75, 15);

        getContentPane().add(aisService);
        aisService.setBounds(80, 255, 325, 21);
        aisService.setText(SERVICE_HEADER.MS_SUPP_RADIO_CHECK_RQ.getAisService());

        aisMsgIdLbl.setText("Ais-Msg-id:");
        getContentPane().add(aisMsgIdLbl);
        aisMsgIdLbl.setBounds(5, 295, 75, 15);


        getContentPane().add(aisMsgId);
        aisMsgId.setBounds(80, 295, 325, 21);
        aisMsgId.setText(SERVICE_HEADER.MS_SUPP_RADIO_CHECK_RQ.getAisMsgId());


        supplementLbl.setText("Header:");
        getContentPane().add(supplementLbl);
        supplementLbl.setBounds(5, 325, 75, 15);


        getContentPane().add(emptyReceived);
        emptyReceived.setBounds(420, 245, 140, 25);
        emptyReceived.setText("Empty Received");
        emptyReceived.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                receivedMessages.setText(null);
            }
        });

        getContentPane().add(jia);
        jia.setBounds(80, 325, 75, 21);
        jia.setText("+");
        jia.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                headNumActionPerformed(evt);
            }
        });
        getContentPane().add(jian);
        jian.setBounds(200, 325, 75, 21);
        jian.setText("clean");
        jian.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                for (JTextField jtf : supplementHeadList) {
                    jtf.setText(null);
                }
            }
        });

        sendBtn.setText("Send");
        sendBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                sendBtnActionPerformed(evt);
            }
        });

        getContentPane().add(sendBtn);
        sendBtn.setBounds(420, 285, 75, 25);


        sendAudioPersonStartBtn.setText("sendAudio(Person)start");
        sendAudioPersonStartBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                sendBtnActionPerformedAudio(evt, true,false);
            }
        });

        getContentPane().add(sendAudioPersonStartBtn);
        sendAudioPersonStartBtn.setBounds(420, 340, 140, 25);

        sendAudioStartBtn.setText("sendAudio(group)start");
        sendAudioStartBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                sendBtnActionPerformedAudio(evt, true,true);
            }
        });

        getContentPane().add(sendAudioStartBtn);
        sendAudioStartBtn.setBounds(420, 390, 140, 25);


        sendAudioCloseBtn.setText("sendAudio_close");
        sendAudioCloseBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                sendBtnActionPerformedAudio(evt, false,true);
            }
        });

        getContentPane().add(sendAudioCloseBtn);
        sendAudioCloseBtn.setBounds(420, 440, 140, 25);

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width - 800) / 2, (screenSize.height - 800) / 2, 1300, 820);

    }

    private void headNumActionPerformed(ActionEvent evt) {
        jiaNumY += 30;
        JTextField jText = new JTextField();
        jText.setText("Content-Type: text/plain");
        supplementHeadList.add(jText);
        getContentPane().add(supplementHeadList.get(supplementHeadList.size() - 1));
        supplementHeadList.get(supplementHeadList.size() - 1).setBounds(80, 325 + jiaNumY, 325, 21);

    }

    private void sendBtnActionPerformedAudio(ActionEvent evt, boolean audio,boolean isGroup) {
        String to = this.toAddress.getText();
        if (audio) {
            try {
                String address = to.substring(to.indexOf("@") + 1).split(":")[0];
                HashMap<String, String> map = new HashMap<>();

                // 创建SDP消息，描述RTP服务器的地址和端口
                int pt = RandomUtil.randomInt(20000, 30000);
                //设置发送端口
                sipLayer.rtcrtpHeaderExample.setIP(address);
                sipLayer.rtcrtpHeaderExample.setPORT(pt);

                String sdpMessage = "" +
                        "v=0\r\n" +
                        "o=Excera 0 0 IN IP4 " + sipLayer.getHost() + "\r\n" +
                        "s=AisDispatcher\r\n" +
                        "c=IN IP4 " + address + "\r\n" +
                        "t=0 0\r\n" +
                        "m=audio " + pt + " RTP/AVP 8\r\n" +
                        "a=rtpmap:8 PCMA/8000\r\n" +
                        "a=floor\r\n" +
                        "a=smf\r\n";

                System.out.println("发送前请先发送注册>>>REGISTER");
                System.out.println(sdpMessage);
                map.put("Content-Type", "application/sdp");
                map.put("methodType", Request.INVITE);
                map.put("Subject", "dmr call");
                if(isGroup){
                    //组呼
                    map.put("Ais-Reach", "group");
                }else {
                    //个呼
                    map.put("Ais-Reach", "individual");
                }
                map.put("Ais-Options", "priority=3;slot=1");
//                sipLayer.rtcrtpHeaderExample.setAudioSendSta(audio);
                sipLayer.sendMessage(to, sdpMessage.getBytes(), map);//开始发送音频
                sipLayer.rtcrtpHeaderExample.setAudioSendSta(1);//开始发送音频状态 启动待发送
            } catch (Throwable e) {
                e.printStackTrace();
                this.receivedMessages.append("ERROR sending audio: " + e.getMessage() + "\n");
            }
        } else {
            try {
                sipLayer.rtcrtpHeaderExample.setAudioSendSta(0);//开始发送音频状态 断开
//                sipLayer.rtcrtpHeaderExample.setAudioSendSta(audio);//停止发送音频
                Request request =  sipLayer.rtcrtpHeaderExample.getRequest();
                request.setMethod(Request.BYE);
                sipLayer.sendRequest(request);

            } catch (SipException | ParseException e) {
                e.printStackTrace();
                this.receivedMessages.append("ERROR sending BYE: " + e.getMessage() + "\n");
            }
        }
    }

    private void sendBtnActionPerformed(ActionEvent evt) {

        try {
            String to = this.toAddress.getText();
            String message = this.sendMessages.getText();
            String aisService = this.aisService.getText();
            String aisMsgId = this.aisMsgId.getText();
            String methodType = this.c1.getSelectedItem().toString();

            HashMap<String, String> map = new HashMap<>();
            map.put("methodType", methodType);

            if (StrUtil.isNotBlank(aisService)) {
                map.put("Ais-Service", aisService);
            }
            if (StrUtil.isNotBlank(aisMsgId)) {
                map.put("Ais-Msg-id", aisMsgId);
            }
            for (JTextField jtf : supplementHeadList) {
                String[] jtfText = jtf.getText().split(":");
                if (jtfText.length > 1) {
                    map.put(jtfText[0], jtfText[1]);
                }
            }
            sipLayer.sendMessage(to, message.getBytes(StandardCharsets.UTF_8), map);
        } catch (Throwable e) {
            e.printStackTrace();
            this.receivedMessages.append("ERROR sending message: " + e.getMessage() + "\n");
        }

    }

    public void processMessage(String sender, String message) {
        this.receivedMessages.append("From " +
                sender + ": " + message + "\n");
    }

    public void processError(String errorMessage) {
        this.receivedMessages.append("ERROR: " +
                errorMessage + "\n");
    }

    public void processInfo(String infoMessage) {
        this.receivedMessages.append(
                infoMessage + "\n");
    }
}
